using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TextSupport
{
	// View of a TextFrame onto a System.Drawing.Graphics
	public class TextFrameView
	{
		TextCaret _caret;

		// Caret position: Line number, and position within that line
		int _caretLine = 0;
		public int CaretLine
		{
			get { return _caretLine; }
		}

		int _caretColumn = 0;
		public int CaretColumn
		{
			get { return _caretColumn; }
		}

		// Return the insertion point as an index into the original
		// text frame that we're editing.
		public int CaretIndex
		{
			get
			{
				return _caretColumn;
			}
		}

		public RectangleF CaretRect
		{
			get
			{
				TextDisplayLine tdl = _displayLines[_caretLine];

				Graphics g = _surface.GetGraphics();

                Size sz = TextRenderer.MeasureText(tdl.Text.Substring(0, _caretColumn), _surface.GetDefaultFont());
				Size szY = TextRenderer.MeasureText("Iy", _surface.GetDefaultFont());

				RectangleF extent = _surface.GetExtent();
				RectangleF rc = new RectangleF(extent.Left + sz.Width, extent.Top + tdl.Y, 1, szY.Height-1);

				return rc;
			}
		}

		List<TextDisplayLine> _displayLines = new List<TextDisplayLine>();

		private IEditSurface _surface;
		public IEditSurface Surface
		{
			get { return _surface; }
			set { _surface = value; }
		}
	
		TextFrame _tf;
		public TextFrameView(TextFrame tf, IEditSurface surface)
		{
			_surface = surface;
			_tf = tf;
			_caret = new TextCaret(this);
		}

        [DllImport("GDI32.dll")]
        static extern bool ExtTextOut(IntPtr hdc, int X, int Y, uint fuOptions,
           [In] ref RECT lprc, string lpString, uint cbCount, int[] lpDx);

        [DllImport("GDI32.dll")]
        public static extern bool DeleteObject(IntPtr objectHandle);

        [DllImport("GDI32.dll")]
        public static extern IntPtr SelectObject(IntPtr dc, IntPtr objectHandle); 

		public void Paint(Graphics g)
		{
			Font f = _surface.GetDefaultFont();

			foreach (TextDisplayLine line in _displayLines)
			{
                RectangleF srcRect = this.CaretRect;
                RECT rc = new RECT((int)srcRect.Left, (int)srcRect.Top, (int)srcRect.Right, (int)srcRect.Bottom);

                TextRenderer.DrawText(g, line.Text, f, new Point(0, line.Y), Color.Black);
			}

			_caret.Draw(g);
		}

		public void OnCursorLeft()
		{
			if (_caretColumn > 0)
			{
				_caretColumn--;
			}
		}

		public void OnCursorRight()
		{
			TextDisplayLine dispLine = _displayLines[_caretLine];
			if (_caretColumn < (dispLine.Text.Length))
				_caretColumn++;
		}

		// Text buffer changed
		public void UpdateLayout()
		{
			_displayLines.Clear();

			Graphics g = _surface.GetGraphics();

			int ypos = 0;
			Font f = _surface.GetDefaultFont();

            Size lineExtent = TextRenderer.MeasureText("Iy", f);

			foreach (TextLine line in _tf.Lines)
			{
				_displayLines.Add(new TextDisplayLine(line.Text, ypos));
				ypos += (int)lineExtent.Height;
			}
		}

		public void DrawCaret()
		{
			_caret.DrawCaret();
		}

		public void EraseCaret()
		{
			_caret.EraseCaret();
		}

		public void ToggleCaret()
		{
			_caret.ToggleCaret();
		}
	}
}
